#include "pcan.h"

/*
 * Data is in two dimension, where cols represent
 * dimensions and rows represent values,
 *
 */
PCAN::PCAN(Mat &input)
{
    src = input.clone();
    if(src.data)
    {
        rows = src.rows;
        cols = src.cols;
    }

    PCA pca(input, Mat(), CV_PCA_DATA_AS_ROW, cols - 1);

    Mat compress(rows, cols-1, input.type());
    Mat recons(rows, cols, input.type());

    pca.project(input, compress);
    pca.backProject(compress, recons);


    for(int i = 0; i < recons.rows; i++)
    {
        for(int j = 0; j < recons.cols; j++)
        {
            qDebug() << recons.at<double>(i, j);
        }
        qDebug() << " ll ";
    }
}


PCAN::~PCAN()
{
}

void PCAN::finalData()
{
    if(!src.data) return ;

    Mat pMat;

    Mat meanSub(rows, cols, CV_64FC1);
    projectionMat(pMat, meanSub);

    Mat fMat(pMat.rows, src.rows,CV_64FC1);

    gemm(pMat, meanSub, 1.0, Mat(), 0.0, fMat, CV_GEMM_B_T);

//    int w = fMat.cols;
//    int h = fMat.rows;

//    for(int i = 0; i < h; i++)
//    {
//        for(int j = 0; j < w; j++)
//        {
//            qDebug() << fMat.at<double>(i, j) << " === ";
//        }
//        qDebug() << "----";
//    }
}

void PCAN::projectionMat(Mat &projMat, Mat &meanSub)
{

    Mat covMat(cols, cols, CV_64FC1);

    meanMat(meanSub);
    gemm(meanSub, meanSub, 1.0, Mat(), 0.0, covMat, CV_GEMM_A_T);

    SVD svd(covMat);

    int index = 0;
    int i, j;
    for(i = 0; i < svd.w.rows; i++)
    {
        if(svd.w.at<double>(i, 0) == 0)
        {
            index = i;
            break;
        }
        index++;
    }
//    qDebug()<< "---------------------------------------" ;
//    for(int i = 0; i < svd.w.rows; i++)
//    {
//        for(int j = 0; j < svd.w.cols; j++)
//        {
//            qDebug() << svd.w.at<double>(i, j);
//        }
//    }

//    qDebug()<< "---------------------------------------" ;

    projMat.create(index, cols, CV_64FC1);

//    qDebug() << svd.w.rows << " svd " << svd.w.cols;

//    qDebug()<< "---------------------------------------" ;
//    for(int i = 0; i < svd.u.rows; i++)
//    {
//        for(int j = 0; j < svd.u.cols; j++)
//        {
//            qDebug() << svd.u.at<double>(i, j);
//        }
//    }

//    qDebug()<< "---------------------------------------" ;
//    for(i=0; i<index; i++)
//    {
//        for(j=0; j<cols; j++)
//        {
//            projMat.at<double>(i, j) = svd.u.at<double>(i, j);
//        }
//    }
}

/*
 *  Convert 'src' to mean-subtracted data
 *
 */
void PCAN::meanMat(Mat &meanSub)
{
    // Each row of 'src'
    Mat line;
    Scalar avg;
    double value = 0.0;
    int i, j;

    for(j = 0; j < cols; j++)
    {
        line = src.col(j);
        avg = mean(line);

        for(i = 0; i < rows; i++)
        {
            value = src.at<double>(i, j) - (double)avg(0);
            meanSub.at<double>(i, j) = value;
        }
    }
}


